Enable migration of a domain to the local machine - some timing
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 20 Apr 2006 16:32:12 +0000 (17:32 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 20 Apr 2006 16:32:12 +0000 (17:32 +0100)
issues needed to be resolved by executing certain code early/later
Restore the physical to machine array such that balloon-allocated
pages can be deallocated.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
linux-2.6-xen-sparse/drivers/xen/tpmback/common.h
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c

index 44a3d4c9e923b5dcc4f67cb8f49b4c75efcdc52b..f08e797e829adf03de7be6ae042541bb14e91853 100644 (file)
@@ -49,6 +49,7 @@ typedef struct tpmif_st {
 
        grant_handle_t shmem_handle;
        grant_ref_t shmem_ref;
+       struct page *pagerange;
 } tpmif_t;
 
 void tpmif_disconnect_complete(tpmif_t * tpmif);
index c31c3fdf6e6f992f1a5bab33c22753f698eda682..7a7ca4c7ed4c4a8fd1103d4728191271f9e62c96 100644 (file)
@@ -22,7 +22,6 @@ LIST_HEAD(tpmif_list);
 
 static tpmif_t *alloc_tpmif(domid_t domid, long int instance)
 {
-       struct page *page;
        tpmif_t *tpmif;
 
        tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
@@ -35,9 +34,10 @@ static tpmif_t *alloc_tpmif(domid_t domid, long int instance)
        tpmif->tpm_instance = instance;
        atomic_set(&tpmif->refcnt, 1);
 
-       page = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
-       BUG_ON(page == NULL);
-       tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+       tpmif->pagerange = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
+       BUG_ON(tpmif->pagerange == NULL);
+       tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(
+                                           page_to_pfn(tpmif->pagerange));
 
        list_add(&tpmif->tpmif_list, &tpmif_list);
        num_frontends++;
@@ -49,6 +49,7 @@ static void free_tpmif(tpmif_t * tpmif)
 {
        num_frontends--;
        list_del(&tpmif->tpmif_list);
+       balloon_dealloc_empty_page_range(tpmif->pagerange, TPMIF_TX_RING_SIZE);
        kmem_cache_free(tpmif_cachep, tpmif);
 }
 
@@ -115,11 +116,11 @@ int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
                .cmd = EVTCHNOP_bind_interdomain,
                .u.bind_interdomain.remote_dom = tpmif->domid,
                .u.bind_interdomain.remote_port = evtchn,
-        };
+       };
 
-        if (tpmif->irq) {
-                return 0;
-        }
+       if (tpmif->irq) {
+               return 0;
+       }
 
        if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
                return -ENOMEM;
index cb7cc74e218198d230ae2b26419c5f46afce960e..9ed254195e9d98f4a5bfad4dbb78914baad292ab 100644 (file)
@@ -271,6 +271,7 @@ int _packet_write(struct packet *pak,
                struct gnttab_map_grant_ref map_op;
                struct gnttab_unmap_grant_ref unmap_op;
                tpmif_tx_request_t *tx;
+               unsigned long pfn, mfn, mfn_orig;
 
                tx = &tpmif->tx->ring[i].req;
 
@@ -293,9 +294,12 @@ int _packet_write(struct packet *pak,
                        DPRINTK(" Grant table operation failure !\n");
                        return 0;
                }
-               set_phys_to_machine(__pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT,
-                                   FOREIGN_FRAME(map_op.
-                                                 dev_bus_addr >> PAGE_SHIFT));
+
+               pfn = __pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT;
+               mfn = FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT);
+               mfn_orig = phys_to_machine_mapping[pfn];
+
+               set_phys_to_machine(pfn, mfn);
 
                tocopy = MIN(size - offset, PAGE_SIZE);
 
@@ -307,6 +311,8 @@ int _packet_write(struct packet *pak,
                }
                tx->size = tocopy;
 
+               set_phys_to_machine(pfn, mfn_orig);
+
                gnttab_set_unmap_op(&unmap_op, MMAP_VADDR(tpmif, i),
                                    GNTMAP_host_map, handle);
 
index 422abd0551498b751da6e40e94ff7ca7ba805d09..61b9250e8dba36609593b0c29a2a210e607acb4d 100644 (file)
@@ -49,6 +49,8 @@ static int tpmback_remove(struct xenbus_device *dev)
 {
        struct backend_info *be = dev->data;
 
+       if (!be) return 0;
+
        if (be->backend_watch.node) {
                unregister_xenbus_watch(&be->backend_watch);
                kfree(be->backend_watch.node);
@@ -119,37 +121,9 @@ static void backend_changed(struct xenbus_watch *watch,
                return;
        }
 
-       if (be->is_instance_set != 0 && be->instance != instance) {
-               printk(KERN_WARNING
-                      "tpmback: changing instance (from %ld to %ld) "
-                      "not allowed.\n",
-                      be->instance, instance);
-               return;
-       }
-
        if (be->is_instance_set == 0) {
-               be->tpmif = tpmif_find(dev->otherend_id,
-                                      instance);
-               if (IS_ERR(be->tpmif)) {
-                       err = PTR_ERR(be->tpmif);
-                       be->tpmif = NULL;
-                       xenbus_dev_fatal(dev,err,"creating block interface");
-                       return;
-               }
                be->instance = instance;
                be->is_instance_set = 1;
-
-               /*
-                * There's an unfortunate problem:
-                * Sometimes after a suspend/resume the
-                * state switch to XenbusStateInitialised happens
-                * *before* I get to this point here. Since then
-                * the connect_ring() must have failed (be->tpmif is
-                * still NULL), I just call it here again indirectly.
-                */
-               if (be->frontend_state == XenbusStateInitialised) {
-                       frontend_changed(dev, be->frontend_state);
-               }
        }
 }
 
@@ -186,6 +160,7 @@ static void frontend_changed(struct xenbus_device *dev,
                 */
                tpmif_vtpm_close(be->instance);
                device_unregister(&be->dev->dev);
+               tpmback_remove(dev);
                break;
 
        case XenbusStateUnknown:
@@ -279,6 +254,18 @@ static int connect_ring(struct backend_info *be)
                                 dev->otherend);
                return err;
        }
+
+       if (!be->tpmif) {
+               be->tpmif = tpmif_find(dev->otherend_id,
+                                      be->instance);
+               if (IS_ERR(be->tpmif)) {
+                       err = PTR_ERR(be->tpmif);
+                       be->tpmif = NULL;
+                       xenbus_dev_fatal(dev,err,"creating vtpm interface");
+                       return err;
+               }
+       }
+
        if (be->tpmif != NULL) {
                err = tpmif_map(be->tpmif, ring_ref, evtchn);
                if (err) {